(function($){
	$.fn.extend({
		/*id,pagination,checkable,automatic,cutLine,
		 afterReady,onChecksChanged,onDoubleClick,ajax,sortable,
		 dataSet,tip,afterSort,onRenderItem,onItemClick*/
		datatable:function(options) {
			var opt = {
				'sortColumnKey':null,
				'sortState':false
			};
			$.extend(opt, options);
			
			var $this = this;
			
			// 渲染选中状态
			var renderCheckedState = function($tbody, opt) {
				opt.multiple || $tbody.find("tr").removeClass("active");
				
				// 再将当前选中的激活
				$($tbody.find("input[data-type='datatable-checkbox']")).each(function(){
					if (this.checked) {
						$(this).closest("tr").addClass("active");
						var curr = new Date();
						$(this).closest("tr").attr("data-active-time",curr.getTime());
					} else {
						$(this).closest("tr.active").removeClass("active");
					}
				});
				
				if (opt.multiple){
					var $allCheckedCheckbox = $tbody.find("input:checked[data-type='datatable-checkbox']");
					var allCheckedState = opt.data.length == $allCheckedCheckbox.length;
					$tbody.closest("table.m-table").find("thead input[data-type='datatable-checkbox']").prop("checked",allCheckedState);
					// 调用onChecked回调函数,参数 checkItems,checkAll,currentItem
					if (opt.onChecksChanged){
						var checkItems = [];
						var currentItem = null;
						var lastActiveTime = -1;
						$tbody.find("input:checked[data-type='datatable-checkbox']").closest("tr").each(function(){
							var rowNum = $(this).attr("row-index");
							var activeTime = $(this).data("active-time");
							if (activeTime > lastActiveTime) {
								currentItem = opt.data[rowNum];
								lastActiveTime = activeTime;
							}
							checkItems.push(opt.data[rowNum]);
						});
						opt.onChecksChanged(checkItems,allCheckedState,currentItem);
					}
				}
				
			};
			
			// 构造datatable
			var buildDatatable = function(data) {
				// 在排序前缓存选中状态
				var cacheCheckedStateOnPreSort = function() {
					
				};
				
				// 输出表格body
				var outputTBody = function($tbody, opt, data) {
					// 当data没有数据/不合法/为NULL时，给一个空表
					$tbody.empty();
					if (!data || !ObjectUtil.isArray(data) || data.length == 0) {
						outputEmptyBody($tbody, opt);
						return ;
					}
					
					var setColumnText = function($text, text, defaultText) {
						if (StringUtil.isEmpty(text) && StringUtil.isNotEmpty(defaultText)) {
							$text.text(defaultText);
						} else {
							$text.text(text);
						}
					};
					
					// 输出行
					var outputRow = function(opt, columns, item, $tr, rowNumber) {
						if (opt.checkable) {
							var $checkboxTd = $("<td data-column-checkbox='true'><input type='checkbox' data-type='datatable-checkbox'></td>");
							$tr.append($checkboxTd);
						}
						if (opt.showLineNumber) {
							var $rowNumber = $("<td data-column-rownum='true'></td>");
							$rowNumber.text(rowNumber);
							$tr.append($rowNumber);
						}
						
						$.each(columns, function(index, column) {
							if (!column.visiable) {
								return ;
							}
							var $td = $("<td></td>");
							$td.attr({
								'column-key':column.name,
								'column-index':index
							});
							
							// text的优先级最低
							var text = item[column.name];
							if (text == null) {
								text = '';
							}
							
							var textStr = text;
							
							// dtext优先级其次
							var dtext = null;
							if (column.dropdown) {
								var dropdown = window[column.dropdown];
								if (dropdown.type == 'drop_constant' && dropdown.dropItems) {
									/*drop_constant:id,emptyText,dropItems{"${value}":{}...}*/
									/*dropItem:{value,text,find,view}*/
									var dropItem = dropdown.dropItems[text];
									textStr = dropItem.text;
									
									// dropItem.className简约模式<span class="">xxx</span>
									if (dropItem.className) {
										dtext = $("<span></span>");
										dtext.addClass(dropItem.className);
										dtext.text(textStr);
									}
									
									// dropItem.view优先级高于dropItem.className
									// dropItem.view模式
									if (dropItem.view) {
										dtext = $(dropItem.view);
										var $tText = null;
										if (dropItem.find) {
											$tText = dtext.find(dropItem.find);
											if ($tText.length <= 0) {
												$tText = null;
											}
										} else {
											$tText = dtext;
										}
										if ($tText != null) {
											setColumnText($tText, dropItem.text, dropdown.emptyText);
										}
									}
									if (dtext == null) {
										dtext = textStr;
									}
								}
							}
							
							// vtext优先级较高
							var vtext = null;
							if (column.dropView) {
								var dropView = window[column.dropView];
								// dropView:{id,dropItems[{title,template,view,name,onClick}...]}
								if (dropView.dropItems) {
									var $container = $("<div class='oper-btn-group'></div>");
									vtext = $container;
									
									$.each(dropView.dropItems, function(key, dropItem){
										// alert("key = " + key + ', item = ' + JSON.stringify(item));
										// 先看看template
										if (dropItem.template) {
											var DROP_VIEW_TEMPLATE = $.store.get("DROP_VIEW_TEMPLATE");
											if (!DROP_VIEW_TEMPLATE) {
												DROP_VIEW_TEMPLATE = {
													'edit':"<button type='button'><i class='fa fa-fw fa-edit'></i></button>",
													'delete':"<button type='button'><i class='fa fa-trash fa-fw'></i></button>",
													'hand-right':"<button type='button'><i class='fa fa-hand-o-right fa-fw'></i></button>",
													'undo':"<button type='button'><i class='fa fa-undo fa-fw'></i></button>",
													'download':"<button type='button'><i class='fa fa-download fa-fw'></i></button>",
												};
											}
											var btn = DROP_VIEW_TEMPLATE[dropItem.template];
											if (StringUtil.isBlank(btn)){
												throw new Error("lui.datatable:" + dropItem.template + "模板不存在");
											}
											var $btn = $(btn);
											$btn.off("click").on('click', function(e) {
												e.stopPropagation();
												e.preventDefault();
												if (StringUtil.isNotBlank(dropItem.onClick)) {
													var clickFunc = eval(dropItem.onClick);
													var row = rowNumber - 1;
													clickFunc(item, e, row);
												} 
											});
											if (dropItem.size != null) {
												var $icon = $btn.find("i");
												$icon.css("font-size", ( dropItem.size * 13 ) + "px");
											}
											dropItem.title && $btn.attr("title", dropItem.title);
											$container.append($btn);
										}
										
									});
								}
							}
							
							// rtext优先级最高
							var rtext = null;
							if (opt.onRenderItem) {
								// colName,text,indexStr,mItem
								var row = rowNumber - 1;
								var tmptext = opt.onRenderItem(column.name, text, index, item, row);
								if (tmptext != null) {
									rtext = tmptext;
								}
							}
							
							// 根据优先级裁定，究竟用text/dtext/rtext中的哪一个
							var ftext = null;
							if (rtext != null ) {
								ftext =rtext;
							} else if (dtext != null) {
								ftext = dtext;
							} else if (vtext != null) {
								ftext = vtext;
							} else {
								ftext = text;
							}
							
							var $text = $("<p class='column-p'></p>");
							column.width && $text.css('max-width',column.width);
							if (opt.cutLine) {
								$text.addClass("cut-line");
								if (StringUtil.isString(ftext)) {
									opt.tip && $td.attr('title',ftext);
								} else {
									if (StringUtil.isNotEmpty(textStr)) {
										opt.tip && $td.attr('title',textStr);
									} else {
										opt.tip && $td.attr('title',text);
									}
								}
							}
							if (column.align) {
								$text.addClass('m-float-' + column.align);
								$text.addClass('m-align-' + column.align);
							}
							if (StringUtil.isString(ftext)) {
								$text.text(ftext);
							} else {
								$text.append(ftext);
							}
							$td.append($text);
							$tr.append($td);
						});
					};
					
					$.each(data, function(index, item){
						var $tr = $("<tr></tr>");
						$tr.attr({
							'row-index':index
						});
						if (opt.dataset.idField) {
							$tr.attr("data-id-value", item[opt.dataset.idField]);
						}
						// 单击事件
						var _time=null;
						$tr.on('click',function(e){
							clearTimeout(_time);
							// myKey:行被选中
							if(!opt.multiple || !opt.checkable) {		
								$tbody.find("tr[data-selected='true']").removeAttr("data-selected");
								$tbody.find("tr[row-index='"+index+"']").attr("data-selected","true");
							}
							if (opt.checkable){
								if (!opt.multiple){
									var $checkedCheckbox = $tbody.find("input:checked[data-type='datatable-checkbox']");
									var $checkRow = $checkedCheckbox.closest("tr");
									var rowNum = $checkRow.attr("row-index");
									if ($(this).attr('row-index') != rowNum) {
										$checkedCheckbox.prop('checked',false);
									} else {
										if ($(this).find("input[data-type='datatable-checkbox']").prop("checked")) {
											$checkRow.attr('data-selected', false);
										}
									}
								}
								var checkedState = !$(this).find("input[data-type='datatable-checkbox']").prop("checked");
								$(this).find("input[data-type='datatable-checkbox']").prop("checked",checkedState);
								// 切换当前行的选中状态
								renderCheckedState($tbody, opt);
							}
							
							_time=setTimeout(function(){
								opt.onItemClick && opt.onItemClick(index,item);				
							},300);
						});
						$tr.on('dblclick',function(e){
							clearTimeout(_time);
							opt.onDoubleClick && opt.onDoubleClick(index,item);
						});
						outputRow(opt, opt.dataset.columns, item, $tr, index + 1);
						$tbody.append($tr);
					});
				};
				
				// 输出表格头部
				var outputTHead = function($thead, opt, $container) {
					var $tr = $thead.find("tr");
					var columns = opt.dataset.columns;
					opt.dataset.getColumnSize = function() {
						return $tr.find("th[data-head='true']").length;
					};
					if (opt.checkable) {
						var $checkableColumn = $("<th data-head='true'></th>");
						if (opt.multiple) {
							var $checkbox = $("<input type='checkbox' data-type='datatable-checkbox'>");
							$checkbox.on("click", function(e){
								e.stopPropagation();
								var $tbody = $container.find("tbody");
								var $allCheckedCheckbox = $tbody.find("input:checked[data-type='datatable-checkbox']");
								var allCheckedState = !($allCheckedCheckbox.length == opt.data.length);
								$(this).prop("checked",allCheckedState);
								$tbody.find("input[data-type='datatable-checkbox']").each(function(){
									$(this).prop('checked',allCheckedState);
									$(this).closest("tr").toggleClass("active", allCheckedState);
								});
							});
							
							$checkableColumn.append($checkbox);
						}
						$tr.append($checkableColumn);
					}
					if (opt.showLineNumber) {
						var $lineNumberColumn = $("<th data-head='true' data-column-rownum='true' title='行号'>#</th>");
						$tr.append($lineNumberColumn);
					}
					$.each(columns, function(index, column) {
						if (!column.visiable) {
							return ;
						}
						var $column = $("<th data-head='true'></th>");
						var display = column.display;
						var sort = column.sort;
						var name = column.name;
						$column.text(display);
						$column.attr({
							'column-key':name,
							'column-index':index
						});
						column.width && $column.css('width', column.width);
						if (sort && opt.sortable) {
							$column.addClass('table-sort');
							$column.off('click').on('click', function(e) {
								var $this = $(this);
								$this.removeClass("sort-asc"); // 移除升序列class
								$this.removeClass("sort-desc"); // 移除降序列class
								var key = $this.attr("column-key");
								
								if(key != opt.sortColumnKey){
									opt.sortState = undefined;
								}
								
								// 切换排序状态
								opt.sortState = opt.sortState == undefined ? true : !opt.sortState; // true:asc,false:desc 
								opt.sortColumnKey = key;
								var className = opt.sortState == true ? "sort-asc":"sort-desc";
								$this.addClass(className);
								// 缓存排序前的状态
								if (opt.checkable){
									cacheCheckedStateOnPreSort();
								}
								// myKey:数据排序
								opt.data.sort(ArrayUtil.by(key, opt.sortState));
								// 重新tbody
								outputTBody($container.find("tbody"), opt, opt.data);
								// myKey:排序后的回调
								opt.afterSort && opt.afterSort(key, opt.sortState);
							});
						}
						$tr.append($column);
					});
				};
				
				// 当数据为空时，输出一个空的提示
				var outputEmptyBody = function($tbody, opt) {
					var EMPTY_PROMPT = "未找到相关数据";
					var $tr = $("<tr data-empty-row='true'><td></td></tr>");
					$tr.find("td")
    					.attr('colspan', opt.dataset.getColumnSize())
    					.text(EMPTY_PROMPT);
					$tbody.append($tr);
				};
				
				$this.empty();
				
				var $container = $("<table class='m-table' width='100%'></table>");
				var $thead = $("<thead><tr></tr></thead>");
				var $tbody = $("<tbody></tbody>");
				$container.append($thead);
				$container.append($tbody);
				
				$this.append($container);
				
				opt.$container = $container;
				
				outputTHead($thead, opt, $container);
				outputTBody($tbody, opt, data);
			};
			
			// 重写ajax的send方法
			opt.ajax.osend = opt.ajax.send;
			opt.ajax.send = function(reset) {
				if (reset == true || reset == null) {
					(!StringUtil.isString(opt.pagination) && opt.pagination) && opt.pagination.reset();
				}
				opt.ajax.osend();
			};
			
			opt.ajax.embedFunction('onSuccess', function(data,xhr,status){
				opt.data = data.info.data;
				buildDatatable(data.info.data);
				if (StringUtil.isNotEmpty(opt.pagination)) {
					if (StringUtil.isString(opt.pagination)) {
						opt.pagination = window[opt.pagination];
					}
					if (opt.pagination){
						opt.pagination.count = data.info.count;
						opt.pagination.refresh(false);
					}
				}
				opt.afterReady && opt.afterReady(data);
			}, opt.ajax);
			
			var _datatable = {
				'getBody':function() {
					return this.$container.find('tbody');
				},
				'getDataSet':function() {
					return this.dataset;
				},
				'getAjax':function() {
					return this.ajax;
				},
				'setPagination':function(pagination) {
					this.pagination = pagination;
				},
				'getPagination':function() {
					return this.pagination;
				},
				'getSize':function() {
					return this.data.length;
				},
				'refresh':function() {
					this.getAjax().send(true);
				},
				'getCurrentItem':function() {
					if (opt.mutiple) {
						if (opt.$container.find('tr.active').length == 1) {
							var rowNum = opt.$container.find('tr.active').attr('row-index');
							return opt.data[rowNum];
						}
						return null;
					} else {
						var rowNum = opt.$container.find('tr[data-selected="true"]').attr('row-index');
						return opt.data[rowNum];
					}
				},
				// 必须在dataSet标签上设置idField属性才有效
				'getItemById':function(idVal) {
					if (opt.dataset.idField) {
						var set = new GenericSet();
						return set.getItemByKey(opt.dataset.idField, idVal);
					}
					throw new Error("你需要在dataSet标签上设置idField属性才能调用getItemById方法");
				},
				'getData':function() {
					return opt.data;
				},
				'selectItem':function(rowNum) {
					var $row = opt.$container.find("tr[row-index='" + rowNum + "']");
					var $activeRows = opt.$container.find("tr.active");
					var $selectedRow = opt.$container.find("tr[data-selected='true']");
					var checkedCheckbox = opt.$container.find("input:checked[type='checkbox'][data-type='datatable-checkbox']");
					if (opt.checkable) {
						$row.find("input[type='checkbox'][data-type='datatable-checkbox']").prop('checked',true);
						if (!opt.multiple) {
							// multiple = false
							$activeRows.removeClass("active");
							$selectedRow.removeAttr("data-selected");
							checkedCheckbox.prop('checked',false);
							$row.attr("data-selected",true);
						} else {
							var time = (new Date()).getTime();
							$row.attr("data-active-time",time).addClass('active');
						}
						$row.addClass("active",true);
					} else {
						$selectedRow.removeAttr("data-selected");
						$row.attr("data-selected",true);
					}
				},
				'selectItemById':function(id) {
					var rowNum = opt.$container.find("tr[data-id-value='"+id+"']").attr("row-index");
					this.selectItem(rowNum);
				},
				'selectItems':function(rowNumArr) {
					if (ArrayUtil.hasData(rowNumArr)) {
						if ( rowNumArr.length == 1) {
    						this.selectItem(rowNumArr[0]);
    						return ;
						}
						if (!opt.multiple) {
							this.selectItem(rowNumArr[0]);
							return ;
						}
						var that = this;
						$.each(rowNumArr, function(index, item) {
							that.selectItem(item);
						});
					}
				},
				'selectItemsByIds':function(idArr) {
					var arr = [];
					$.each(idArr, function(index, item) {
						var rowNum = opt.$container.find("tr[data-id-value='"+item+"']").attr("row-index");
						arr.push(rowNum);
					});
					this.selectItems(arr);
				}
			};
			$.extend(_datatable, opt);
			return _datatable;
		},
		// {$pagination,id,ajax,pageSize,rows}
		pagination: function(options) {
			var opt = {};
			opt = $.extend(opt, options);
			var $pageChoice = opt.$pagination.find("select[name='rows']");
			if (!opt.showPageChoice) {
				opt.$pagination.find(".pageSize").hide();
			}
			if (StringUtil.isNotEmpty(opt.pageChoice)) {
				$pageChoice.empty();
				var pageChoiceArr = opt.pageChoice.split(",");
				$.each(pageChoiceArr, function(index, item){
					var $option = $("<option></option>");
					$option.attr("value",item).text(item);
					$pageChoice.append($option);
				});
				var pageChoiceSet = new GenericSet(pageChoiceArr);
				if (StringUtil.isNotEmpty(opt.pageSize) && pageChoiceSet.hasItem(opt.pageSize)) {
					$pageChoice.val(opt.pageSize);
				}
			}
			// count,rows
			var pagination = {
				'defaultPage':opt.$pagination.find('input[name="page"]').val(),
				'defaultRows':opt.pageSize,
				'defaultCount':0,
				'count':0,
				'page':opt.$pagination.find('input[name="page"]').val(),
				'rows':opt.pageSize,
				'refresh':function(query) {
					// 只有当当前页码真实改变时才赋值，否则会触发死循环
					var $pagination = opt.$pagination;
					var datatable = opt.datatable;
					
					$pagination.find('#maxPage').text(this.getMaxPage());
					if($pagination.find('#currentPage').val() != this.page) {
						$pagination.find('#currentPage').val(this.page);
					}
					$pagination.find('#rows').val(this.rows);
					$pagination.find('#count').text(this.count);
					
					query = (query == undefined || query)?true:query;
					query && datatable && datatable.getAjax().send(false);
				},
				'getMaxPage':function() {
					var val = parseInt(this.count/this.rows);
					if(this.count % this.rows != 0){
						val = val+1;
					}
					if (val == 0 ) val = 1;
					if(isNaN(this.count % this.rows)){
						val = 1;
						this.$pagination.find('#currentPage').val(0);
						this.$pagination.find('#count').text(0);
					}
					return val;
				},
				'reset':function() {
					this.page = this.defaultPage;
					this.rows = this.defaultRows;
					this.count = this.defaultCount;
					this.refresh(false);
				},
				'pageChanged':function(option) {
					switch(option){
					case 'homePage': // 首页
						this.page=1;
						break;
					case 'endPage': // 最后一页
						this.page=this.getMaxPage();
						break;
					case 'nextPage': // 下一页
						if(this.page == this.getMaxPage()){
							$.messager.info("提示：已经是最后一页了");
						}
						if(this.page < this.getMaxPage()) {
							this.page++;
						}
						break;
					case 'prevPage': // 上一页
						if(this.page == 1){
							new $.messager.info("提示：已经是第一页了");
						}
						if(this.page>1){
							this.page--;
						}
						break;
					case 'rowsChanged': // 总页数改变
						this.rows = this.$pagination.find('#rows').val();
						break;
					case 'currentPage': // 当前页码输入时改变
						var currentPage = this.$pagination.find('#currentPage').val();
						
						// 校验输入合法性，输入的值必须是大于等于1且小于最大页码数的整数值
						var type = /^[0-9]*[0-9][0-9]*$/;
					    var re = new RegExp(type);
						if( currentPage.match(re)!=null){
							currentPage = parseInt(currentPage);
							if(currentPage >= 1 && currentPage <= this.getMaxPage()){
								this.page = currentPage;
							}
						}
						break;
					}
					this.refresh();
				}
			};
			$.extend(pagination, opt);
			return pagination;
		}
	});
})(window.jQuery);

